#include "main.h"

static void RCC_SetClock_36MHz(void);
static void RCC_SetClock_64MHz(void);
static void RCC_SetClock_72MHz(void);

RCCClassStruct RCCClass = {
	.Set36MHz = RCC_SetClock_36MHz,
	.Set64MHz = RCC_SetClock_64MHz,
	.Set72MHz = RCC_SetClock_72MHz,
};

//#define use_36MHz
//#define use_64MHz
//#define use_72MHz

/**
  * @brief  设置时钟频率36Mhz
	* @param  None
  * @retval None
  */
static void RCC_SetClock_36MHz(void)
{
#ifdef use_36MHz
	__IO uint32_t StartUpCounter = 0, HSEStatus = 0;
	 RCC_DeInit();
	
	/* SYSCLK, HCLK, PCLK2 and PCLK1 configuration ---------------------------*/
	/* Enable HSI */
	RCC->CR |= ((uint32_t)RCC_CR_HSION);
	
	/* Wait till HSI is ready and if Time out is reached exit */
	do
	{
		HSEStatus = RCC->CR & RCC_CR_HSIRDY;
		StartUpCounter++;
	} while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));
	if((RCC->CR & RCC_CR_HSIRDY) != RESET)
	{
		HSEStatus = (uint32_t)0x01;
	}
	else
	{
		HSEStatus = (uint32_t)0x00;
	} 
	if(HSEStatus == (uint32_t)0x01)
	{
		/* Enable Prefetch Buffer */
		FLASH->ACR |= FLASH_ACR_PRFTBE;
		/* Flash 2 wait state */
		FLASH->ACR &= (uint32_t)((uint32_t)~FLASH_ACR_LATENCY);
		FLASH->ACR |= (uint32_t)FLASH_ACR_LATENCY_2; 
		
		/* HCLK = SYSCLK */
		RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;
		 
		/* PCLK2 = HCLK */
		RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1;
		
		/* PCLK1 = HCLK */
		RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV1;
		
		/* PLL configuration: PLLCLK = HSI / 2 * 9 = 36MHz */
		RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLMULL));
		RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSI_Div2| RCC_CFGR_PLLMULL9);
		
		/* Enable PLL */
		RCC->CR |= RCC_CR_PLLON;
		/* Wait till PLL is ready */
		while((RCC->CR & RCC_CR_PLLRDY) == 0);
		/* Select PLL as system clock source */
		RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
		RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL;
		/* Wait till PLL is used as system clock source */
		while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)0x08);
	}
	else
	{ /* If HSE fails to start-up, the application will have wrong clock 
	onfiguration. User can add here some code to deal with this error */
	}
#endif
}
/**
  * @brief  设置时钟频率64Mhz
	* @param  None
  * @retval None
  */
static void RCC_SetClock_64MHz(void)
{
#ifdef use_64MHz
	__IO uint32_t StartUpCounter = 0, HSEStatus = 0;
	 RCC_DeInit();
	
	/* SYSCLK, HCLK, PCLK2 and PCLK1 configuration ---------------------------*/
	/* Enable HSI */
	RCC->CR |= ((uint32_t)RCC_CR_HSION);
	
	/* Wait till HSI is ready and if Time out is reached exit */
	do
	{
		HSEStatus = RCC->CR & RCC_CR_HSIRDY;
		StartUpCounter++;
	} while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));
	if((RCC->CR & RCC_CR_HSIRDY) != RESET)
	{
		HSEStatus = (uint32_t)0x01;
	}
	else
	{
		HSEStatus = (uint32_t)0x00;
	} 
	if(HSEStatus == (uint32_t)0x01)
	{
		/* Enable Prefetch Buffer */
		FLASH->ACR |= FLASH_ACR_PRFTBE;
		/* Flash 2 wait state */
		FLASH->ACR &= (uint32_t)((uint32_t)~FLASH_ACR_LATENCY);
		FLASH->ACR |= (uint32_t)FLASH_ACR_LATENCY_2; 
		
		/* HCLK = SYSCLK */
		RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;
		 
		/* PCLK2 = HCLK */
		RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1;
		
		/* PCLK1 = HCLK */
		RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV2;
		
		/* PLL configuration: PLLCLK = HSI / 2 * 16 = 64 MHz */
		RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLMULL));
		RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSI_Div2| RCC_CFGR_PLLMULL16);	
		/* Enable PLL */
		RCC->CR |= RCC_CR_PLLON;
		/* Wait till PLL is ready */
		while((RCC->CR & RCC_CR_PLLRDY) == 0);	
		/* Select PLL as system clock source */
		RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
		RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL;
		/* Wait till PLL is used as system clock source */
		while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)0x08);
	}
	else
	{ /* If HSE fails to start-up, the application will have wrong clock 
	onfiguration. User can add here some code to deal with this error */
	}
#endif
}
/**
  * @brief  设置时钟频率72Mhz
	* @param  None
  * @retval None
  */
static void RCC_SetClock_72MHz(void)
{
#ifdef use_72MHz
	RCC_DeInit();    																						// RCC system reset(for debug purpose)
	RCC_HSEConfig(RCC_HSE_ON); 																	// Enable HSE
	char HSEStartUpStatus = RCC_WaitForHSEStartUp(); 								// Wait till HSE is ready
	if(HSEStartUpStatus != 0)                  					// 当HSE准备完毕切振荡稳定后
	{
		RCC_HCLKConfig(RCC_SYSCLK_Div1);                   				// HCLK = SYSCLK
		RCC_PCLK2Config(RCC_HCLK_Div1);                  					// PCLK2 = HCLK
		RCC_PCLK1Config(RCC_HCLK_Div2);                  					// PCLK1 = HCLK/2
		FLASH_SetLatency(FLASH_Latency_2);                 				// Flash 2 wait state
		FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);  		// Enable Prefetch Buffer
		RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);   		// PLLCLK = 8MHz * 9 = 72 MHz
		RCC_PLLCmd(ENABLE);            // Enable PLL
		while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);				// Wait till PLL is ready

		RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);    		  			// Select PLL as system clock source
		while(RCC_GetSYSCLKSource() != 0x08);       							// Wait till PLL is used as system clock source

	}
#endif
}
